package com.tutucms.service.admin.service;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.tutucms.common.exception.InvokException;
import com.tutucms.common.util.CharUtil;
import com.tutucms.common.util.DateUtil;
import com.tutucms.service.common.SessionHolder;
import com.tutucms.service.configuration.AliOssConfig;
import com.tutucms.service.configuration.AliStsConfig;
import com.tutucms.service.model.vo.AliStsInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

/**
 * Created by wangxudong on 2020/03/07.
 *
 * @version: 1.0
 * @modified :
 */
@Slf4j
@Service
public class OssService {

    @Autowired
    private AliOssConfig aliOssConfig;

    @Autowired
    private AliStsConfig aliStsConfig;

    @Autowired
    private ClientBuilderConfiguration clientBuilderConfiguration;

    private static final String BATH_PATH = "tutu/service/store/";

    // 上传并返回访问地址
    public String store(String originFileName, byte[] data) {
        log.info("文件上传" + originFileName);
        OSS ossClient = new OSSClientBuilder().build(aliOssConfig.getEndpoint(),
                aliOssConfig.getAccessKeyId(), aliOssConfig.getAccessKeySecret(), clientBuilderConfiguration);

        String key = generateKey(originFileName);
        try {
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(data.length);
            objectMetadata.setObjectAcl(CannedAccessControlList.PublicRead);
            PutObjectRequest putObjectRequest = new PutObjectRequest(aliOssConfig.getBucketName(),
                    key, new ByteArrayInputStream(data), objectMetadata);

            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);

            return getBaseUrl(key);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            throw new InvokException("文件上传错误:" + ex.getMessage());
        } finally {
            ossClient.shutdown();
        }

    }

    // 上传并返回访问地址
    public String store(InputStream inputStream, long contentLength, String contentType, String originFileName) {

        log.info("文件上传" + originFileName);
        OSS ossClient = new OSSClientBuilder().build(aliOssConfig.getEndpoint(),
                aliOssConfig.getAccessKeyId(), aliOssConfig.getAccessKeySecret(), clientBuilderConfiguration);
        String key = generateKey(originFileName);
        try {
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(contentLength);
            objectMetadata.setContentType(contentType);
            PutObjectRequest putObjectRequest = new PutObjectRequest(aliOssConfig.getBucketName(),
                    key, inputStream, objectMetadata);
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);
            putObjectRequest.setMetadata(metadata);

            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);

            return getBaseUrl(key);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            throw new InvokException("文件上传错误:" + ex.getMessage());
        } finally {
            ossClient.shutdown();
        }
    }

    public AliStsInfoVo fetchAliYunOssSts() {
        try {
            // 添加endpoint（直接使用STS endpoint，前两个参数留空，无需添加region ID）
            DefaultProfile.addEndpoint("", "", "Sts", aliStsConfig.getEndpoint());

            // 构造default profile（参数留空，无需添加region ID）
            IClientProfile profile = DefaultProfile.getProfile("", aliStsConfig.getAccessKeyId(),
                    aliStsConfig.getAccessKeySecret());

            // 用profile构造client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            AssumeRoleRequest request = new AssumeRoleRequest();
            request.setMethod(MethodType.POST);
            request.setRoleArn(aliStsConfig.getRoleArn());
            // 自定义参数
            request.setRoleSessionName("ip" + SessionHolder.getRemoteIp());
            request.setDurationSeconds(3600L);
            AssumeRoleResponse response = client.getAcsResponse(request);

            AliStsInfoVo vo = new AliStsInfoVo();
            vo.setExpiration(DateUtil.getMillisByString(response.getCredentials().getExpiration()));
            vo.setAccessKeyId(response.getCredentials().getAccessKeyId());
            vo.setAccessKeySecret(response.getCredentials().getAccessKeySecret());
            vo.setSecurityToken(response.getCredentials().getSecurityToken());
            log.debug("RequestId: " + response.getRequestId());

            return vo;
        } catch (ClientException e) {

            log.error(String.format("获取阿里云sts错误：%s(%s)", e.getErrMsg(), e.getErrCode()));
            throw new InvokException("获取sts出现错误", e);
        }
    }

    public AliOssConfig getAliOssConfig(){

        return aliOssConfig;
    }

    private String getBaseUrl(String key) {

        return "https://" + aliOssConfig.getBucketName() + "." + aliOssConfig.getEndpoint() + "/" + key;
    }

    private String generateKey(String originName) {
        String extName = originName.substring(originName.lastIndexOf("."));
        return BATH_PATH + System.currentTimeMillis() + CharUtil.getRanNumber(6) + extName;
    }

}
